/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.com.losalpes.marketplace.pirfq.beans;

import co.com.losalpes.marketplace.pirfq.bos.CotizacionBO;
import co.com.losalpes.marketplace.pirfq.bos.FabricanteBO;
import co.com.losalpes.marketplace.pirfq.bos.FabricanteCotizacionBO;
import co.com.losalpes.marketplace.pirfq.entities.Cotizacion;
import co.com.losalpes.marketplace.pirfq.entities.FabricanteCotizacion;
import co.com.losalpes.marketplace.pirfq.exceptions.CotizacionNoExisteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author marketplace
 */
@Stateless
public class RFQBean implements RFQRemote, RFQLocal {

    @PersistenceContext
    private EntityManager em;
   
    public static final String ABIERTAS_COTIZACION = "A";
    public static final String CERRADAS_COTIZACION = "C";
    public static final String CANCELADAS = "F";

    /**
     * Se establece el estado de la cotización en RADICADO
     * @param cotizacionBO
     * @return  numero de la cotizacion
     */
    public String crearCotizacion(CotizacionBO cotizacionBO) {

        String numero = "RFQ" + System.currentTimeMillis();
       
        cotizacionBO.setNumero(numero);
        Cotizacion cotizacion = new Cotizacion(cotizacionBO);
        em.persist(cotizacion);
       
        return numero;
    }

    /**
     *
     * @param cotizacion
     * @param fabricantes
     * @return
     */
    public boolean asignarFabricantesACotizacion(String numeroCotizacion, List<FabricanteBO> fabricantes) throws CotizacionNoExisteException{

        //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            throw new CotizacionNoExisteException("El numero de cotizacion ingresado no existe");
        }else{
            cot = listCotizaciones.get(0);
        }

        Long ideCotizacion = cot.getId();

        for(FabricanteBO fabricante : fabricantes){
            FabricanteCotizacionBO fabricanteCotizacionBo = new FabricanteCotizacionBO();
            fabricanteCotizacionBo.setId_cotizacion(ideCotizacion);
            fabricanteCotizacionBo.setId_fabricante(fabricante.getId());

            FabricanteCotizacion fabricanteCotizacion =  new FabricanteCotizacion(fabricanteCotizacionBo);
            em.persist(fabricanteCotizacion);
        }

        return true;
    }

    /**
     * Permite obtener cotizaciones ofertadas por un fabricante
     * @param idFabricante
     * @param estado
     * @return
     */
    public List<CotizacionBO> obtenerCotizacionesPorFabricante(Long idFabricante, String estado) {

        //quemado Prueba
         //List<CotizacionBO> list = new ArrayList<CotizacionBO>();
         //fin
        Query q = em.createNamedQuery("obtenerCotizacionesFabricanteEstado");
        q.setParameter("id_fabricante", idFabricante);
        q.setParameter("estado", estado);
       
        List<FabricanteCotizacion> fabricantesCotizaciones = (List<FabricanteCotizacion>)q.getResultList();

        List<CotizacionBO> listCotizacionBO = new ArrayList<CotizacionBO>();

        if(fabricantesCotizaciones != null && !fabricantesCotizaciones.isEmpty()){
            for (FabricanteCotizacion fabCotizac : fabricantesCotizaciones){
               
                Long idCotizacion = fabCotizac.getId_cotizacion();
               
                Query queryCotizacion = em.createNamedQuery("getCotizacionByID");
                queryCotizacion.setParameter("id", idCotizacion);
               
                List<Cotizacion> cotizaciones = (List<Cotizacion>) queryCotizacion.getResultList();
               
                if(cotizaciones != null && !cotizaciones.isEmpty()){
                   CotizacionBO cotizacionBO = cotizaciones.get(0).toBO();
                   
                   if(cotizacionBO != null){
                    listCotizacionBO.add(cotizacionBO);
                   }
                }
               

            }
        }
       
        //descomente para test
        //list.add(new CotizacionBO(10, 200000, null, null, 9, "Yogurt", "Lacteos"));

        return listCotizacionBO;
    }
   
     /**
     * Permite obtener las cotizaciones establecidas por el comercio
     * @param idComercio
     * @param estado
     * @return
     */
    public List<CotizacionBO> obtenerCotizacionesPorComercio(Long idComercio, String estado) {

        Query q = em.createNamedQuery("getCotizacionComercioEstado");
        q.setParameter("id_comercio", idComercio);
        q.setParameter("estado", estado);

        List<Cotizacion> cotizaciones = (List<Cotizacion>) q.getResultList();
        List<CotizacionBO> listCotizacionBO = new ArrayList<CotizacionBO>();

        if(cotizaciones != null && !cotizaciones.isEmpty()){
            for (Cotizacion cotizacionEntity : cotizaciones){
                CotizacionBO cotizacionBO = cotizacionEntity.toBO();
                if(cotizacionBO != null){
                    listCotizacionBO.add(cotizacionBO);
                }
            }
        }

        return listCotizacionBO;
    }


    /**
     *
     * @param fabricanteCotizacionBo
     * @return
     */
    public Boolean ofertarCotizacion(FabricanteCotizacionBO fabricanteCotizacionBo) {
       
        FabricanteCotizacion ofertar = new FabricanteCotizacion(fabricanteCotizacionBo);
        em.persist(ofertar);
       
        return true;
    }

    public Boolean actualizarEstadoCotizacion(String numeroCotizacion, String estado) throws CotizacionNoExisteException{
       
        //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            throw new CotizacionNoExisteException("El numero de cotizacion a actualizar no existe");
        }else{
            cot = listCotizaciones.get(0);
        }
       
        cot.setEstado(estado);
       
        em.persist(cot);

        return true;
    }

    public List<FabricanteCotizacionBO> obtenerOfertasFabricantes(String numeroCotizacion) throws CotizacionNoExisteException{

        List<FabricanteCotizacionBO> list = new ArrayList<FabricanteCotizacionBO>();
       
                //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            throw new CotizacionNoExisteException("El numero de cotizacion ingresado no existe");
        }else{
            cot = listCotizaciones.get(0);
        }
       
        if(cot != null){
            List<FabricanteCotizacion> ofertas = new ArrayList<FabricanteCotizacion>(0);
            Long idCotizacion = cot.getId();
            Query consOfertas = em.createNamedQuery("getOfertaFabricante");
            consOfertas.setParameter("idCotizacion", idCotizacion);
           
            ofertas = consOfertas.getResultList();
           
            if(ofertas != null && !ofertas.isEmpty()){
                for (FabricanteCotizacion fabCotizacion : ofertas){
                    list.add(fabCotizacion.toBO());
                }
            }
        }
       
       

        //list.add(new FabricanteCotizacionBO(Long.parseLong("1"), Long.parseLong("9"), "RESPONDIDA"));
        //list.add(new FabricanteCotizacionBO(Long.parseLong("2"), Long.parseLong("9"), "RESPONDIDA"));

        return list;
    }

    /**
     * Asigna el fabricante ganador, y cierra la cotización
     * @param numeroCotizacion
     * @param idFabricante
     * @return
     */
    public Boolean asignarCotizacionGanadora(String numeroCotizacion, String idFabricante) throws CotizacionNoExisteException{
       
       
        //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            throw new CotizacionNoExisteException("El numero de cotizacion ingresado no existe");
        }else{
            cot = listCotizaciones.get(0);
        }
       
        cot.setEstado(CERRADAS_COTIZACION);
        Long idFabricanteSeleccionado = Long.parseLong(idFabricante);
        cot.setId_fabricante_seleccionado(idFabricanteSeleccionado);

        return true;
    }

    public boolean asignarFabricanteACotizacion(String numeroCotizacion, FabricanteBO fabricantes) throws CotizacionNoExisteException {
       //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            return false;
        }else{
            cot = listCotizaciones.get(0);
            cot.setId_fabricante_seleccionado(fabricantes.getId());
            em.merge(cot);
            return true;
        }
    }

    public boolean editarFechaMaximaCierreCotizacion(String numeroCotizacion, Date fechaMaximaCierre) {
       //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            return false;
        }else{
            cot = listCotizaciones.get(0);
        }
        
        if(cot != null){
            cot.setFecha_cierre(fechaMaximaCierre);
            em.merge(cot);
            return true;
        }else{
            return false;
        }   
    }

    public boolean editarFechaMaximaEntregaCotizacion(String numeroCotizacion, Date fechaMaximaEntrega) {
        //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            return false;
        }else{
            cot = listCotizaciones.get(0);
        }
        
        if(cot != null){
            cot.setFecha_entrega(fechaMaximaEntrega);
            em.merge(cot);
            return true;
        }else{
            return false;
        }
    }

    public boolean editarFabricanteCotizacion(FabricanteCotizacionBO fabricanteCotizacion) {
        Query quer = em.createNamedQuery("getOfertaFabricanteByID");
        Long idFabricante = fabricanteCotizacion.getId_fabricante();
        Long idCotizacion = fabricanteCotizacion.getId_cotizacion();
        quer.setParameter("idCotizacion", idCotizacion);
        quer.setParameter("idFabricante", idFabricante);
        List<FabricanteCotizacion> ofertas = quer.getResultList();
        
        if (ofertas != null && !ofertas.isEmpty()) {
            FabricanteCotizacion oferta = ofertas.get(0);
           
            oferta.setCantidad(fabricanteCotizacion.getCantidad());
            
           if(fabricanteCotizacion.getFecha_entrega() != null){
               oferta.setFecha_entrega(fabricanteCotizacion.getFecha_entrega());
            }        

            if(fabricanteCotizacion.getPrecio() != null){
                oferta.setPrecio(fabricanteCotizacion.getPrecio());
            }
            em.merge(oferta);
            return true;
        } else {
            return false;
        }
    }

    /**
     * permite validar si una operación de edición es posible dependiendo del tipo de edición, 
     * (cambio fecha cierre, cambio fecha entrega), es posible el cambio únicamente antes de la fecha límite de la 
     * convocatoria o de entrega - SI SE PUEDE EDITAR LA FECHA DE CIERRE SE PUEDE CANCELAR
     * @param numeroCotizacion
     * @return 
     */
    public boolean validarEdicion(String numeroCotizacion) {
        //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            return false;
        }else{
            cot = listCotizaciones.get(0);
        }
        
        long fechaActual = new Date().getTime();
        if(cot != null){
            long fechaEntrega = cot.getFecha_entrega().getTime();
            if(fechaActual < fechaEntrega){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    
    /**
     * Permite validar si una cancelación es posible dependiendo del estado actual de la operación, es posible cancelar la 
     * operación únicamente antes de la fecha de cierre de la convocatoria, pues despúes de seleccionar el fabricante la PO se genera automáticamente
     * @param numeroCotizacion
     * @return 
     */
    public boolean validarCancelacion(String numeroCotizacion) {
        //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numeroCotizacion);

        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones.isEmpty()){
            return false;
        }else{
            cot = listCotizaciones.get(0);
        }
        
        long fechaActual = new Date().getTime();
        if(cot != null){
            long fechaCierre = cot.getFecha_cierre().getTime();
            long fechaEntrega = cot.getFecha_entrega().getTime();
            
            if((fechaActual < fechaCierre) && (fechaActual < fechaEntrega) ){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
    
    /**
     * Este metodo permite consultar las cotizaciones por su numero especifico.
     * @param numSeguimiento
     * @return
     */
    public CotizacionBO consultarCotizacionporNumSeguimiento(String numSeguimiento) {
        //buscar x numero cotizacion
        Query quer = em.createNamedQuery("getCotizacionPorNumero");
        quer.setParameter("numero", numSeguimiento);

        CotizacionBO boCotizacion = new CotizacionBO();
        List<Cotizacion> listCotizaciones = quer.getResultList();
        Cotizacion cot = null;

        if(listCotizaciones != null && !listCotizaciones.isEmpty()){
            cot = listCotizaciones.get(0);
            boCotizacion = cot.toBO();
        }
        return boCotizacion;
    }
}
